package org.luffhat.config;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonStreamContext;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.util.ReflectionUtils;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

/**
 * @Description
 * @Author ljb
 * @Date 2022-01-14
 */
@Configuration
@Slf4j
public class JacksonConfig {

    @Bean
    @Primary
    @ConditionalOnMissingBean(ObjectMapper.class)
    public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
        ObjectMapper objectMapper = builder.createXmlMapper(false).build();
        objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
            @Override
            public void serialize(Object value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                JsonStreamContext outputContext = jsonGenerator.getOutputContext();
                //获取到被序列化的对象（包含的所有的属性）
                Object currentValue = outputContext.getCurrentValue();
                //获取当前对象中被序列化的属性
                String currentFeildName = outputContext.getCurrentName();
                //匹配牛逼的首字母大写问题
                currentFeildName = currentFeildName.substring(0, 1).toLowerCase() + currentFeildName.substring(1);
                // 一个被序列化的对象找到了，这个当前序列化的属性也找到了，所以如果借用反射方式可以获取当前的类型
                if (currentValue != null) {
                    Field findField = ReflectionUtils.findField(currentValue.getClass(), currentFeildName);
                    if (findField == null) {
                        log.info("当前属性名称:[{}],没有找到对应的实体类中的属性", currentFeildName);
                    }
                    // 获取字段的类型
                    Class<?> filedType = findField.getType(); // 这里开始写入数据
                    //log.info("属性:[{}]的类型为：[{}]" ,currentFeildName, filedType.getName());
                    switch (filedType.getName()) {
                        case "java.lang.String":
                            jsonGenerator.writeString("");
                            break;
                        case "java.lang.Boolean":
                            jsonGenerator.writeBoolean(false);
                            break;
                        case "java.lang.Integer":
                            jsonGenerator.writeNumber(0);
                            break;
                        case "java.lang.Double":
                        case "java.lang.Float":
                            jsonGenerator.writeObject(0.0);
                            break;
                        case "java.util.Set":
                            jsonGenerator.writeObject(new HashSet<>());
                            break;
                        case "java.util.Map":
                            jsonGenerator.writeObject(new HashMap<>());
                            break;
                        case "java.util.List":
                            jsonGenerator.writeObject(new ArrayList<>());
                            break;
                        case "java.util.Date":
                            jsonGenerator.writeObject("");
                            break;
                        case "java.lang.Object":
                            jsonGenerator.writeObject("{}");
                            break;
                        default:
                            log.info("当前属性:[{}]的类型：[{}]没匹配逻辑，返回原值", filedType.getName(), currentFeildName);
                            jsonGenerator.writeObject(value);
                    }
                } else {
                    System.out.println("没有匹配到实体类-------" + currentFeildName);
                    jsonGenerator.writeObject(value);
                }
            }
        });
        return objectMapper;
    }
}
